package ALBasicCommon;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Random;

public class ALBasicCommonFun
{
    private static Random g_randomObj = new Random();
    private static String g_sHexStrIdxString = "0123456789abcdef";
    
    /*****************
     * 将字节转化为int对象
     * 
     * @author alzq.z
     * @time   Feb 19, 2013 11:30:30 AM
     */
    public static int byte2int(byte value) { return (int)value & 0xFF; }
    
    /************
     * 根据位置设置对应字节的对应位置值
     * 
     * @author alzq.z
     * @time   2016年5月18日 上午1:31:48
     */
    public static byte setByteTag(byte _srcValue, int _pos, boolean _isTrue)
    {
        if(_isTrue)
            return (byte)(_srcValue | (0x01 << _pos));
        else
            return (byte)(_srcValue & ~(0x01 << _pos));
    }
    public static boolean getByteTag(byte _srcValue, int _pos)
    {
        return ((_srcValue & (0x01 << _pos)) != 0);
    }
    
    /*****************
     * 将2个short转化为int对象
     * 
     * @author alzq.z
     * @time   Feb 19, 2013 11:30:30 AM
     */
    public static int mergeShort(short _s1, short _s2)
    {
        return (((int)_s1) << 16) | _s2;
    }
    public static int mergeShortNum(int _s1, int _s2)
    {
        return (_s1 << 16) | _s2;
    }
    
    /*****************
     * 将2个int转化为long对象
     * 
     * @author alzq.z
     * @time   Feb 19, 2013 11:30:30 AM
     */
    public static long mergeInt(int _i1, int _i2)
    {
        return (((long)_i1) << 32) | _i2;
    }
    public static int splitMergeIntFirst(long _l)
    {
        return (int)(_l >> 32);
    }
    public static int splitMergeIntSec(long _l)
    {
        return (int)(_l & 0xFFFFFFFF);
    }

    public static boolean getBoolean(ByteBuffer buf)
    {
        if ( buf.get() == 1 )
        {
            return true;
        }
        
        return false;
    }
    
    public static void putBoolean(ByteBuffer buf, boolean bData)
    {
        if ( null == buf )
        {
            return;
        }
        
        if ( bData )
        {
            buf.put((byte)1);
        }
        else {
            buf.put((byte)0);
        }
    }
    
    /****************
     * 从字节数据中获取字符串
     * @param bb
     * @return
     */
    public static String getString(ByteBuffer bb)
    {
        short nStringLen = bb.getShort();
        byte[] byarrString = new byte[nStringLen];
        
        try
        {
            bb.get(byarrString, 0, nStringLen);
        }
        catch (Exception e)
        {
            return "";
        }
        
        String str;
        try
        {
            CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
            str = decoder.decode(ByteBuffer.wrap(byarrString)).toString();
        }
        catch (CharacterCodingException e)
        {
            return "";
        }
        
        return str;
    }
    
    /***********
     * 获取发送字符串所需要的包长度
     * @param str
     * @return
     */
    public static int getStringSize(String str)
    {
        if(null == str || str.isEmpty())
        {
            return 2;
        }
        
        return str.getBytes().length + 2;
    }
    
    /************
     * 将字符串放入字节包中
     * @param _str
     * @param _buf
     */
    public static void putString(String _str, ByteBuffer _buf)
    {
        if (_str != null && _str.length() > 0)
        {
            byte[] sb = _str.getBytes();
            _buf.putShort((short) sb.length);
            _buf.put(sb);
        }
        else
        {
            _buf.putShort((short) 0);
        }
    }
    
    /**************
     * 将字符串转化为字节包
     * @param _str
     * @return
     */
    public static ByteBuffer getStringBuf(String _str)
    {
        if (_str != null && _str.length() > 0)
        {
            byte[] stringByte = _str.getBytes();

            ByteBuffer buf = ByteBuffer.allocate(stringByte.length + 2);
            buf.putShort((short) stringByte.length);
            buf.put(stringByte);
            buf.flip();
            
            return buf;
        }
        else
        {
            ByteBuffer buf = ByteBuffer.allocate(2);
            buf.putShort((short) 0);
            buf.flip();
            
            return buf;
        }
    }
    
    /**
     * 获取当前时间的小时部分（24小时制）
     * @return
     */
    public static int getNowTimeHour()
    {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.HOUR_OF_DAY);
    }
    
    /**
     * 获取当前时间距纪元所经历的秒数
     * @return
     */
    public static int getNowTime()
    {
        int iNowTime = (int) (System.currentTimeMillis() / 1000);
        
        return iNowTime;
    }
    
    /**
     * 获取当前时间距纪元所经历的毫秒数
     * @return
     */
    public static long getNowTimeMS()
    {
        return System.currentTimeMillis();
    }
    
    /**
    * 获取当前时间信息连接起来的数字
    * @return
    */
    public static long getNowTimeNum()
    {
        Calendar calendar = Calendar.getInstance();
        
        long timeNum = calendar.get(Calendar.YEAR);
        timeNum = (timeNum * 100) + calendar.get(Calendar.MONTH) + 1;
        timeNum = (timeNum * 100) + calendar.get(Calendar.DAY_OF_MONTH);
        timeNum = (timeNum * 100) + calendar.get(Calendar.HOUR_OF_DAY);
        timeNum = (timeNum * 100) + calendar.get(Calendar.MINUTE);
        timeNum = (timeNum * 100) + calendar.get(Calendar.SECOND);
        
        return timeNum;
    }
    public static String getNowTimeStr()
    {
        Calendar calendar = Calendar.getInstance();
        
        StringBuilder stringBuild = new StringBuilder(20);
        stringBuild.append(calendar.get(Calendar.YEAR)).append("-")
                        .append(calendar.get(Calendar.MONTH) + 1).append("-")
                        .append(calendar.get(Calendar.DAY_OF_MONTH)).append(" ")
                        .append(calendar.get(Calendar.HOUR_OF_DAY)).append(":")
                        .append(calendar.get(Calendar.MINUTE)).append(":")
                        .append(calendar.get(Calendar.SECOND));
        
        return stringBuild.toString();
    }
    
    /**************
     * 根据新的小时标记划分不同天，并返回日期的标记
     * @company Isg @author alzq.zhf
     * 2014年10月8日 下午3:07:14
     */
    public static int getDayTagByHourSplit(int _hour)
    {
        Calendar calendar = Calendar.getInstance();
        
        if(calendar.get(Calendar.HOUR_OF_DAY) < _hour)
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
        
        //拼凑数据，由于月份从0开始，所以需要加1与客户端匹配
        int tag = calendar.get(Calendar.YEAR);
        tag = (tag * 100) + calendar.get(Calendar.MONTH) + 1;
        tag = (tag * 100) + calendar.get(Calendar.DAY_OF_MONTH);
        
        return tag;
    }
    
    /**
     * 根据刷新小时节点，取当前周天
     * @return
     */
    public static int getCurDayOfWeekByHourSplit(int _hour)
    {
        Calendar calendar = Calendar.getInstance();
        
        if(calendar.get(Calendar.HOUR_OF_DAY) < _hour)
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
        
        int tag = calendar.get(Calendar.DAY_OF_WEEK);
        
        //第1天从周日开始
        if(calendar.getFirstDayOfWeek() == Calendar.SUNDAY)
            tag -=  1;        
        if(0 == tag)
            tag = 7;
        
        return tag;
    }
    
    /**
     * 产生一个处于区间 0<= x < _iRangeLimit 的随机整数
     * @return
     */
    public static int getRandomIntByRange(int _iRangeLimit)
    {
        return Math.abs(g_randomObj.nextInt(_iRangeLimit));
    }
    
    /**
     * 产生一个处于区间 0<= x <= _iRangeLimit 的随机整数
     * @param iDelta
     * @return
     */
    public static int getRandomInt(int _iRangeLimit)
    {
        return Math.abs(g_randomObj.nextInt(_iRangeLimit + 1));
    }
    public static long getRandomLong()
    {
        return Math.abs(g_randomObj.nextLong());
    }
    
    /**
     * 产生一个处于区间 0<= x <= 1 的随机浮点数
     * @param iDelta
     * @return
     */
    public static float getRandomFloat()
    {
        return g_randomObj.nextFloat();
    }
    
    /**
     * 将字节数组转换成十六进制字符串
     * @param iDelta
     * @return
     */
    public static String getHexString(byte[] _buf)
    {
        if(null == _buf || _buf.length <= 0)
            return "0";
        
        //逐个字节处理
        StringBuilder builder = new StringBuilder();
        for(int i = 0; i < _buf.length; i++)
        {
            byte b = _buf[i];
            
            //取前4位
            builder.append(g_sHexStrIdxString.charAt((b >> 4) & 0x0F));
            //取后4位
            builder.append(g_sHexStrIdxString.charAt(b & 0x0F));
        }
        
        return builder.toString();
    }
    public static String getHexString(ByteBuffer _buf)
    {
        if(null == _buf)
            return "";
        
        //记录当前下标位置
        int prePos = _buf.position();
        int len = _buf.limit();
        //逐个字节处理
        StringBuilder builder = new StringBuilder();
        for(int i = 0; i < len; i++)
        {
            byte b = _buf.get();
            
            //取前4位
            builder.append(g_sHexStrIdxString.charAt((b >> 4) & 0x0F));
            //取后4位
            builder.append(g_sHexStrIdxString.charAt(b & 0x0F));
        }
        
        //重置buff下标
        _buf.position(prePos);
        
        return builder.toString();
    }

    /**
     * 将字节数组转换成十六进制字符串
     * @param iDelta
     * @return
     */
    public static byte[] getHexBytes(String _hexStr)
    {
        if (null == _hexStr)
            return null;

        //创建结果数组
        byte[] res = new byte[_hexStr.length() / 2];

        int pos = 0;
        //逐个字符进行处理
        for (int i = 0; i < _hexStr.length(); i++)
        {
            char c = _hexStr.charAt(i);

            //查询c所在的索引
            byte prePos = (byte)g_sHexStrIdxString.indexOf(c);

            //增加索引
            i++;

            c = _hexStr.charAt(i);

            //查询c所在的索引
            byte secPos = (byte)g_sHexStrIdxString.indexOf(c);

            //计算具体数值
            res[pos] = (byte)((prePos << 4) | secPos);
            //下标加1
            pos++;
        }

        return res;
    }
    
    /********************
     * 拷贝队列
     */
    public static <T> void addAllList(ArrayList<T> _srcList, ArrayList<T> _tarList)
    {
    	if(null == _srcList || null == _tarList)
    		return ;
    	
    	if(_srcList.size() > 1024)
    	{
    		_tarList.addAll(_srcList);
    	}
    	else
    	{
    		//逐个拷贝
    		for(int i = 0; i < _srcList.size(); i++)
    		{
    			_tarList.add(_srcList.get(i));
    		}
    	}
    }
    
    /*****************
     * 根据字符拆解字符串的通用函数
     * @param s
     * @param token
     * @return
     */
    public static String[] charSplit(String _s, char _token)
	{
		return charSplit(_s, _token, Integer.MAX_VALUE);
	}
    public static String[] charSplit(String _s, char _token, int _limit)
    {
    	return charSplit(_s, _token,_limit,true);
    }
	public static String[] charSplit(String _s, char _token, int _limit, boolean _bTrim)
	{
		if(null == _s)
			return null;
		
		if(_bTrim)
			_s = _s.trim();
		
		int iStart=0;
		ArrayList<String> arr= new ArrayList<>();
		for(int i=0; i<_s.length(); i++)
		{
			if(_s.charAt(i) == _token)
			{
				String sub = _s.substring(iStart, i);
				arr.add(sub);
				iStart=i+1;
				
				if(arr.size() == _limit - 1)
					break;
			}
		}
		
		arr.add(_s.substring(iStart, _s.length()));
		
		String[] ret= new String[arr.size()];
		return arr.toArray(ret);
	}

	/******************
	 * 将Bytebuffer数据转化为byte数组，进行相关的其他业务
	 * @param byteBuff
	 * @return
	 */
	public static byte[] ByteBfferToBytes(ByteBuffer _byteBuff) 
	{
		if(_byteBuff == null)
			return null;
		
		//记录原先的下标位置
		int oldPositon = _byteBuff.position();
		
		//重置位置到0，以获取所有数据
		_byteBuff.position(0);
		byte[] ret = new byte[_byteBuff.remaining()];
		_byteBuff.get(ret);
		
		//重置下标位置
		_byteBuff.position(oldPositon);
		return ret;
	}
	
	/******************
	 * 从指定的文件路径直接读取对应文件的文本内容
	 * @param _filePath
	 * @return
	 */
	public static String readFileTxt(String _filePath)
	{
		return readFileTxt(_filePath, StandardCharsets.UTF_8);
	}
	public static String readFileTxt(String _filePath, Charset _charSet)
	{
		FileInputStream fis = null;
		InputStreamReader reader = null;
		
		File dealingFile = new File(_filePath);
		if(dealingFile.exists())
		{
			try {
				fis = new FileInputStream(dealingFile);
				reader = new InputStreamReader(fis, _charSet);

				//根据文件长度构建读取缓冲区
				byte[] readRes = new byte[(int)dealingFile.length()];
				//读取文件
				fis.read(readRes);
				
				return new String(readRes);
			} catch (FileNotFoundException e) {
				//文件不存在直接返回空
				return "";
			}catch (IOException e) {
				//读取IO报错，此时直接返回失败
				return "";
			}
			finally
			{
				if(null != reader)
				{
					try {
						reader.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				reader = null;
				
				if(null != fis)
				{
					try {
						fis.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				fis = null;
			}
		}
		else
		{
			return "";
		}
	}

	/*********************
	 * 将指定文本重新写入到文件中，覆盖原先内容
	 * @param _filePath
	 * @param _txt
	 * @return
	 */
	public static boolean rewriteTxtToFile(String _filePath, String _txt)
	{
		return rewriteTxtToFile(_filePath, _txt, StandardCharsets.UTF_8);
	}
	public static boolean rewriteTxtToFile(String _filePath, String _txt, Charset _charset)
	{
		FileOutputStream fos = null;
		OutputStreamWriter writer = null;
		
		File dealingFile = new File(_filePath);
		
		//判断父目录是否存在，如果不存在会引起创建错误
		File parentFile = dealingFile.getParentFile();
        if (!parentFile.exists())
        {
         	if(!parentFile.mkdirs())
         	{
         		System.out.println("can not create dir for file: " + _filePath);
         		return false;
         	}
        }
        
        //写入对应的文件
		try {
			fos = new FileOutputStream(dealingFile);
			writer = new OutputStreamWriter(fos, _charset);

			//写入数据
			writer.write(_txt);
			writer.flush();

			return true;
		} catch (FileNotFoundException e) {
			//文件不存在直接返回空
			return false;
		}catch (IOException e) {
			//读取IO报错，此时直接返回失败
			return false;
		}
		finally
		{
			if(null != writer)
			{
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			writer = null;
			
			if(null != fos)
			{
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			fos = null;
		}
	}

	/***********************
	 * 处理文件每行内容的处理函数，带入处理对象之后根据模板类将会返回一个队列
	 * @param _filePath
	 * @param _lineHandler
	 * @return
	 */
	public static<T> ArrayList<T> handleEachLinesFromFile(String _filePath, _ATALHandleFileLine<T> _lineHandler)
	{
		File file = null;
		FileReader reader = null;
		BufferedReader br = null;
		String strLine = null;
		ArrayList<T> list = new ArrayList<T>();

		//如果没有处理对象则直接返回
		if(null == _lineHandler)
			return list;
		
		try
		{
			//构建文件对象
			file = new File(_filePath);
			//判断文件是否存在
			if(!file.exists())
			{
				//直接返回
				return list;
			}
			
			//构建读取对象
			reader = new FileReader(file);
			br = new BufferedReader(reader);
			
			//针对每行进行读取和处理
			while ((strLine = br.readLine()) != null)
			{
				strLine = strLine.trim();
				if (null != strLine && !strLine.isEmpty())
				{
					//逐行进行处理
					T obj = _lineHandler.handle(strLine);
					//判断是否有正确返回值，有则加入队列
					if(null != obj)
						list.add(obj);
				}
			}
			
			//返回队列
			return list;
		}
		catch (Throwable e)
		{
			System.out.println(e);
			e.printStackTrace();
			
			return list;
		}
		finally
		{
			//释放需要释放的对象
			if (br != null)
			{
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			br = null;
			
			if(null != reader)
			{
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			reader = null;
		}
	}
}
